/*
 * 
 * Copyright 2010 David H Pollack
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 * 
 * 
 */

package fantasy;


import java.io.IOException;
import java.io.StringReader;
import java.util.Date;
import java.util.regex.Pattern;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

/**
 * @author dpollack
 *
 */
public class YahooParseXml {
	
	private PersistenceManager pm = PMF.get().getPersistenceManager();
	
	private static XPath xPath = XPATH.get().newXPath();
	
	private static String XML;
	
	private static Document response;
	
	private Integer game_key;
	
	private String game_type;
	
	private String league_key;
	
	private String league_update_timestamp;
	
	public YahooParseXml() {
		
	}
	
	public void getXmlFromDS(String userkey) 
	throws JDOObjectNotFoundException {
		if(XML == null) {
			try {
				LeagueXml l = pm.getObjectById(LeagueXml.class, userkey);
				XML = l.getLeaguexml();
			} finally {
				setDocResponse();
			}
		}
	}
	
	public void parseForStatics(Node node)
	throws XPathExpressionException {
		league_key = (String)xPath.evaluate("league_key", node, XPathConstants.STRING);
		// Processing for game key.  Will be replaced with game parse
		String regex = "\\.";
		Pattern numSplit = Pattern.compile(regex);
		String[] m = numSplit.split(league_key);
		game_key = Integer.parseInt(m[0]);
		game_type = "unknown";
		if(game_key.equals(238)) {
			game_type = "baseball";
		}
		league_update_timestamp = (String)xPath.evaluate("league_update_timestamp", node, XPathConstants.STRING);
		
	}
	
	public NodeList getXmlNodes(String expression) 
	throws XPathExpressionException {
		NodeList n = (NodeList)xPath.evaluate( expression , response, XPathConstants.NODESET);
		return n;

	}
	
	private void setDocResponse() {
		InputSource is = new InputSource(new StringReader(XML));
		try {
			response = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public StatCategory parseLeagueForCategories(Node node)
	throws NumberFormatException, XPathExpressionException {
			

    	//Get each xpath variable
		Integer stat_id = Integer.parseInt((String)xPath.evaluate("stat_id", node, XPathConstants.STRING));
		String stat_name = (String)xPath.evaluate("name", node, XPathConstants.STRING);
		String stat_display_name = (String)xPath.evaluate("display_name", node, XPathConstants.STRING);
		String stat_position_type = (String)xPath.evaluate("position_type", node, XPathConstants.STRING);

		// Create new StatCategory
		StatCategory s = new StatCategory();
        //Set key after calling function
		//s.setKey(key);
        s.setGameKey(game_key);
        s.setGameType(game_type);
        s.setStatId(stat_id);
        s.setStatName(stat_name);
        s.setStatDisplayName(stat_display_name);
        s.setStatType("stat_type");
        s.setPositionType(stat_position_type);
        s.setStatDivisorType("divisor");
        s.setStatDivisorNum(1);

        return s;
	}
	
	public RosterPositions parseLeagueForPositions(Node node)
	throws NumberFormatException, XPathExpressionException {

    	//Get each xpath variable
		String roster_position = (String)xPath.evaluate("position", node, XPathConstants.STRING);
		Integer roster_position_count = Integer.parseInt((String)xPath.evaluate("count", node, XPathConstants.STRING));
		
		// Create new RosterPositions entity
		RosterPositions r = new RosterPositions();
		r.setRosterPosition(roster_position);
		r.setRosterPositionCount(roster_position_count);
		
		return r;

	}
	
	public LeagueSettings parseLeagueForSettings(Node node) 
	throws NumberFormatException, XPathExpressionException {
		// Get League Variables from XML only if needed
		league_key = (String)xPath.evaluate("league_key", node, XPathConstants.STRING);
    	Integer league_id 	= Integer.parseInt((String)xPath.evaluate("league_id", node, XPathConstants.STRING));
		String league_name = (String)xPath.evaluate("name", node, XPathConstants.STRING);
		String league_url = (String)xPath.evaluate("url", node, XPathConstants.STRING);
		String league_draft_status = (String)xPath.evaluate("draft_status", node, XPathConstants.STRING);
		Integer league_num_teams = Integer.parseInt((String)xPath.evaluate("num_teams", node, XPathConstants.STRING));
		String league_update_timestamp = (String)xPath.evaluate("league_update_timestamp", node, XPathConstants.STRING);
		Date d = new Date();
		d.setTime(Long.parseLong(league_update_timestamp) * 1000);
		String league_draft_type = (String)xPath.evaluate("//draft_type", node, XPathConstants.STRING);
		String league_scoring_type = (String)xPath.evaluate("//scoring_type", node, XPathConstants.STRING);
		Integer league_uses_playoff = Integer.parseInt((String)xPath.evaluate("//uses_playoff", node, XPathConstants.STRING));
		Integer league_uses_faab = Integer.parseInt((String)xPath.evaluate("//uses_faab", node, XPathConstants.STRING));

		// Processing for game key.  Will be replaced with game parse
		String regex = "\\.";
		Pattern numSplit = Pattern.compile(regex);
		String[] m = numSplit.split(league_key);
		game_key = Integer.parseInt(m[0]);
		game_type = "unknown";
		if(game_key.equals(238)) {
			game_type = "baseball";
		}

		// Create new LeagueSettings entity
		LeagueSettings l = new LeagueSettings();
		l.setLeagueKey(league_key);
		l.setGameKey(game_key);
		l.setGameType(game_type);
		l.setLeagueId(league_id);
		l.setLeagueName(league_name);
		l.setNumTeams(league_num_teams);
		l.setsDraftType(league_draft_type);
		l.setDraftStatus(league_draft_status);
		l.setsScoringType(league_scoring_type);
		l.setsUsesPlayoff(league_uses_playoff);
		l.setsUsesFaab(league_uses_faab);
		l.setLeagueUpdateTimestamp(d);
		
		return l;
	}
	
	public LeagueTeams parseLeagueForTeams(Node node) 
	throws XPathExpressionException {
		
		String team_key = (String)xPath.evaluate("team_key", node, XPathConstants.STRING);
    	Integer team_id	= Integer.parseInt((String)xPath.evaluate("team_id", node, XPathConstants.STRING));
		String team_name = (String)xPath.evaluate("name", node, XPathConstants.STRING);
		String team_url = (String)xPath.evaluate("url", node, XPathConstants.STRING);
		  
		Key key = KeyFactory.createKey(LeagueTeams.class.getSimpleName(), team_key);
		  
		LeagueTeams t = new LeagueTeams();
		t.setTeamid(team_id);
		t.setTeamkey(key);
		t.setTeamname(team_name);
		t.setTeamurl(team_url);
		
		NodeList managerNodes = (NodeList)xPath.evaluate("managers/manager", node, XPathConstants.NODESET);
		int nodeManagerCount = managerNodes.getLength();
		for (int k = 0; k < nodeManagerCount; k++) {
			  
			Integer manager_id = Integer.parseInt((String)xPath.evaluate("manager_id", managerNodes.item(k), XPathConstants.STRING));
			String manager_name = (String)xPath.evaluate("nickname", managerNodes.item(k), XPathConstants.STRING);
			
			try {
				xPath.evaluate("is_comanager", node, XPathConstants.STRING);
				t.setComanagerid(manager_id);
				t.setComanagername(manager_name);
			} catch(NullPointerException e) {
				t.setManagerid(manager_id);
				t.setManagername(manager_name);
			}
			  
		}
		return t;
	}
	
	public TeamStats parseLeagueForTeamStats(Node node)
	throws XPathExpressionException {
		
		XPathExpression xpath_stat_id = xPath.compile("stat_id");
		XPathExpression xpath_stat_value = xPath.compile("value");

		Integer stat_id = Integer.parseInt((String)xpath_stat_id.evaluate(node, XPathConstants.STRING));
		Double stat_value = Double.valueOf((String)xpath_stat_value.evaluate(node, XPathConstants.STRING));

		String key_gen = game_type + "-" + stat_id.toString();
		Key key = new KeyFactory.Builder(StatCategory.class.getSimpleName(),key_gen).getKey();
		  
		TeamStats s = new TeamStats();
		s.setStatid(key);
		s.setStatvalue(stat_value);
		
		return s;
		
		
	}
	
	public LeagueStandings parseLeagueForStandings(Node node)
	throws XPathExpressionException {

		XPathExpression xpath_team_key = xPath.compile("team_key");
		XPathExpression xpath_team_points = xPath.compile("team_points/total");
		XPathExpression xpath_team_rank = xPath.compile("team_standings/rank");

		String team_key = (String)xpath_team_key.evaluate(node, XPathConstants.STRING);
		
		String standing_entry_key = team_key + "-" + league_update_timestamp;
		Key stkey = new KeyFactory.Builder(LeagueSettings.class.getSimpleName(),league_key)
			.addChild(LeagueTeams.class.getSimpleName(),team_key)
	  		.addChild(LeagueStandings.class.getSimpleName(), standing_entry_key)
	  		.getKey();
		
	  	Double team_points = Double.valueOf((String) xpath_team_points.evaluate(node, XPathConstants.STRING));
	  	Integer team_rank = Integer.parseInt((String)xpath_team_rank.evaluate(node, XPathConstants.STRING));
	  	
	  	LeagueStandings ls = new LeagueStandings();
	  	ls.setTeamkeystamp(stkey);
		ls.setTeampoints(team_points);
		ls.setTeamrank(team_rank);
		
		return ls;




		
	}

	public Integer getGame_key() {
		return game_key;
	}

	public String getGame_type() {
		return game_type;
	}

	public String getLeague_key() {
		return league_key;
	}
	


}
